package com.xplay.xpocker.room.message.service;

import com.xplay.xpocker.config.MessageEvent;
import com.xplay.xpocker.config.security.CurrentUser;
import com.xplay.xpocker.constant.MessageNoticeEnum;
import com.xplay.xpocker.core.lock.LocalLockServer;
import com.xplay.xpocker.observer.SubscriptionSubject;
import com.xplay.xpocker.room.message.MessageContent;
import com.xplay.xpocker.room.message.AbstractMessageStrategy;
import com.xplay.xpocker.room.message.MessageType;
import com.xplay.xpocker.room.voice.VoiceInfo;
import com.xplay.xpocker.observer.ChannelHandlerManager;
import com.xplay.xpocker.util.JacksonStringUtil;
import com.xplay.xpocker.util.ObjectUtils;
import com.xplay.xpocker.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Service
public class VoiceMessageService extends AbstractMessageStrategy {
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    @Resource
    private RedisUtil redisUtil;

    //连接中
    private int CONN = 1;
    // 连接完成
    private int CONN_SUCCESS = 3;

    @Override
    public void doMessage(String code, MessageContent<Object> data) {
        String message = JacksonStringUtil.objectToString(data.getBody());
        if (ObjectUtils.isEmpty(message)) {
            return;
        }
        VoiceInfo voiceInfo = JacksonStringUtil.objectCase(message, VoiceInfo.class);
        if (voiceInfo == null) {
            return;
        }
        BigDecimal currentUserId = CurrentUser.getUserId();
        voiceInfo.setCurrentUid(currentUserId);
        SubscriptionSubject subject = ChannelHandlerManager.diskPart.get(code);
        switch (voiceInfo.getCmd()) {
            case "conn":
                log.debug("用户:{} 主动加入房间,获取所有用户让当前用户创建OFFER进行交换", currentUserId);
                Set<BigDecimal> onlineUser = new ArrayList<>(subject.getSubjectUsers().values()).stream().filter(item ->
                        item != null && !ChannelHandlerManager.getUserId(item).equals(currentUserId) && item.channel().isOpen()).map(ChannelHandlerManager::getUserId).collect(Collectors.toSet());
                if (onlineUser.size() > 0) {
                    MessageContent.Builder<Object> currentBuilder = MessageContent.Builder.builder(code, MessageType.VOICE.getType(),
                            currentUserId, MessageNoticeEnum.CURRENT);
                    currentBuilder.setMessageFromUid(currentUserId);
                    voiceInfo.setCorrelationUIds(onlineUser);
                    currentBuilder.setBody(voiceInfo);
                    log.debug("用户:{} 正在与:{} 产生信令交换", currentUserId, voiceInfo.getCorrelationUIds());
                    applicationEventPublisher.publishEvent(new MessageEvent(this, currentBuilder.build()));
                } else {
                    log.debug("用户主动发起连接,但是房间不存在任何在线用户");
                }
                break;
            case "offer":
                log.debug("服务器收到OFFER,将用户:{},OFFER发送给:{}", currentUserId, voiceInfo.getRemoteUid());
                MessageContent.Builder<Object> builder = MessageContent.Builder.builder(code, MessageType.VOICE.getType(),
                        voiceInfo.getRemoteUid(), MessageNoticeEnum.CURRENT);
                voiceInfo.addCorrelationUIds(currentUserId);
                builder.setBody(voiceInfo);
                applicationEventPublisher.publishEvent(new MessageEvent(this, builder.build()));
                break;
            case "answer":
                log.debug("服务器收到ANSWER,将用户:{},answer发送给:{}", currentUserId, voiceInfo.getRemoteUid());
                MessageContent.Builder<Object> answerBuilder = MessageContent.Builder.builder(code, MessageType.VOICE.getType(),
                        voiceInfo.getRemoteUid(), MessageNoticeEnum.CURRENT);
                voiceInfo.addCorrelationUIds(currentUserId);
                answerBuilder.setBody(voiceInfo);
                applicationEventPublisher.publishEvent(new MessageEvent(this, answerBuilder.build()));
                break;
            case "candidate":
                log.debug("服务器收到CANDIDATE,将用户:{},candidate发送给:{}", currentUserId, voiceInfo.getRemoteUid());
                String key = getKey(currentUserId, voiceInfo.getRemoteUid());
                redisUtil.set(key, CONN_SUCCESS);
                MessageContent.Builder<Object> candidateBuilder = MessageContent.Builder.builder(code, MessageType.VOICE.getType(),
                        voiceInfo.getRemoteUid(), MessageNoticeEnum.CURRENT);
                voiceInfo.addCorrelationUIds(currentUserId);
                candidateBuilder.setBody(voiceInfo);
                applicationEventPublisher.publishEvent(new MessageEvent(this, candidateBuilder.build()));
                break;
            case "logout":
                log.debug("服务器收到 logout,将用户:{},candidate发送给:{}", currentUserId, voiceInfo.getRemoteUid());
                MessageContent.Builder<Object> logOutBuilder = MessageContent.Builder.builder(code, MessageType.VOICE.getType(),
                        currentUserId, MessageNoticeEnum.OTHER);
                voiceInfo.addCorrelationUIds(currentUserId);
                logOutBuilder.setBody(voiceInfo);
                applicationEventPublisher.publishEvent(new MessageEvent(this, logOutBuilder.build()));
                break;
            default:
                break;
        }

    }

    private String getKey(BigDecimal userIdA, BigDecimal userIdB) {
        int comparisonResult = userIdA.compareTo(userIdB);
        String key;
        if (comparisonResult >= 0) {
            key = userIdB + "_" + userIdA;
        } else {
            key = userIdA + "_" + userIdB;
        }
        return key;
    }

    @Override
    protected int strategyName() {
        return MessageType.VOICE.getType();
    }
}
